/*
* $Id: low_level_init.c,v 1.3 2007/11/23 08:25:07 sunny Exp $
*/
/*******************************************************************************

       UBEC (Uniband Electronic Corp.)

       Project: U-NET01, Ubiquitous network platform

       File: low_level_init.c

       Version: 0.2.3

       Usage: Initial MCU

       Platform: U-NET01 DK with Keil 8051 C compiler

       Reference:

               Silicon Laboratories: C8051F124, C8051F340

               UBEC: UZ2400, UZ2410

       Note :

               Copyright (C) 2007 Uniband Electronic Corporation, All rights reserved

********************************************************************************/

#include "unet.h"

#if defined(__C51__)
    #ifdef I_Am_Coordinator
	#if defined(IOC8051F124) || defined(IOUZ2410)
	unsigned char xdata malloc_mempool [0x2000];
	#elif defined(IOC8051F340)
	unsigned char xdata malloc_mempool [0x1B00];
	#else
		#error "Unknown CPU type."
	#endif
    #else
	unsigned char xdata malloc_mempool [0x800];
    #endif  // #ifdef I_Am_Coordinator

// first stage initialization, called before main(), for all resources without memory system support
// Locate low_level_init in the CSTART module
// If the code model is banked, low_level_init must be declared
// __near_func elsa a ?BRET is performed

__low_level_init(void){
  	/*==================================*/
  	/*  Initialize hardware.            */
  	/*==================================*/

#if defined(IOC8051F124)
    	WDTCN = 0xDE;   //Disable the WDT
    	WDTCN = 0xAD;

	//Program the internal Oscillator
    	SFRPAGE = 0xf; //Setup the SFR page
    	OSCICN = 0x83; //Enable the internal Oscillator, Internal Oscillator is divided by 1

    	while(!(OSCICN & 0x40)); //Wait the clock is ready

	//Program the I/O Port for UART, SPI, and Interrupt
    #ifdef UZIG
      	XBR0 = 0x0f; //Enable the SPI , SMB and UART
     	XBR1 = 0x04;
      	XBR2 = 0x44; //enable the Crossbar
    #else
	XBR0 = 0xF7; //UART0, SPI
     	XBR1 = 0x07; //enable the INT0
      	XBR2 = 0x44; //enable the Crossbar
    #endif

	//Set up the SPI Pin mode
      	P0MDOUT = 0x34; // push-pull spi mode
      	P1MDOUT = 0xFF;
      	P2MDOUT = 0xEF;

    #ifdef UZIG
	//Led pin assign
	P1MDIN &= ~0xf0;  // set Analog Input P1.4 5 6 7
    #endif

	//Set up the external memory interface
      	P4MDOUT |= 0xE0;
      	P5MDOUT |= 0xFF;
      	P6MDOUT |= 0xFF;
      	P7MDOUT |= 0xFF;

      	P4 |= 0xE0;
      	P5 |= 0xFF;
      	P6 |= 0xFF;
      	P7 |= 0xFF;

      	SFRPAGE = 0;

	//Set Interrupt
	IT0 = 0;  // 1, set INT0 as falling edge triggered ,0, set INT0 as level triggered

	//Program the external memory interface
	//6-7: Don't care
	//5: 1->EMIF active on port4-7
	//4: 1->non-multiplexed mode
	//2-3: 01->Below 8K, on Chip, Above 8K external SRAM only
	//0-1: 00->ALE pulse width 1 SYSCLK cycle

	EMI0CF = 0x34;

	// 2007/7/9 13:11, Sunny: refer to the datashet C8051F12x-13x.pdf, Rev 1.4, page 221:
	//	External Memory Configuration, Split Mode without Bank Select:
	//	Note that in order to access off-chip space,
	//	EMI0CN must be set to a page that is not contained in the on-chip address space.
	EMI0CN = 0x20;

	EMI0TC = 0x8A; //Timing 10-0010-10

#elif defined(IOC8051F340)
	PCA0MD = 0x0;	//Disable the WDT

	//Program the internal Oscillator
	OSCICN = 0x83;	//Enable the internal Oscillator
			//Internal Oscillator is divided by 1
	while(!(OSCICN & 0x40));//Wait the clock is ready

	//Program the I/O Port for UART, SPI
	XBR0 = 0x3;	//SPI I/O routed to port pins and UART TX0, RX0 routed to port pins P0.4 and P0.5
	XBR1 = 0x40;	//Crossbar enable

	//Set up the Pin mode
	P0MDOUT = 0x1D;
	P1MDOUT = 0xC0;
	P2MDOUT = 0xFF;
	P3MDOUT = 0xFF;
	P4MDOUT = 0xFF;

	P0SKIP = 0x40;
	P1SKIP = 0xC0;
	P2SKIP = 0xFF;
	P3SKIP = 0xFF;

	//INT0/INT1 Configuration
	IT01CF = 0x67;	//INT1 input is active low and routed to port pin P0.6
	IT1 = 0;	//set INT1 as level triggered

	PX1 = 1;	// set INT1 interrupt high priority
	PS0 = 1;	// set UART0 interrupt high priority

	//Program the external memory interface
	EMI0CN = 0x00;
	EMI0CF = 0x1F;	//EMIF operates in non-multiplexed mode (separate address and data pins) and use external memory only!
	EMI0TC = 0x80;

#elif defined(IOUZ2410)
	P1D = 0x0;
	P1 = 0;

//	CHIPCFG = 0x3b; //enable memory bus
	CHIPCFG = 0x1A;		/* OCI = 1, UzMMI = 1, JTAG = 1 */

    #if (CPU_CLOCK == 20000000L)
//	LREG4D = 0x0;		/* Set MCU Clock = 20MHz */
	spi_lw(0x24D, 0x0);	/* Set MCU Clock = 20MHz */
    #endif
#else
	#error "Unknown CPU type."
#endif

  	/*==================================*/
  	/* Choose if segment initialization */
  	/* should be done or not.           */
  	/* Return: 0 to omit seg_init       */
  	/*         1 to run seg_init        */
  	/*==================================*/
  	return (1);
}
#endif // #if defined(__C51__)

/*
**-----------------------------------------------------------------------------
**
**  Abstract:
**	second stage initialization, the first routine called by main()
**	with interrupt disabled, for all resources require memory system support
**
**  Parameters:
**	None
**
**  Returns:
**	None
**
**-----------------------------------------------------------------------------
*/
void SystemInit( void )
{
	volatile unsigned int i;

	WDTCTL = WDTPW + WDTHOLD;		// Stop WDT

//	BCSCTL1=RSEL2+RSEL1;		// 2MHz
	BCSCTL1=RSEL2+RSEL1+RSEL0;	// 4.9MHz
	do {
		IFG1 &= ~OFIFG;			// Clear OSCFault flag
		for (i = 0xFF; i > 0; i--);	// Time for flag to set
	} while ((IFG1 & OFIFG));		// OSCFault flag still set?

//	DCOCTL=DCO0+DCO1;		// 2MHz
	DCOCTL=DCO0+DCO1+DCO2;		// 4.9MHz

#if 1
	enable_LED_output();
#else
	P5DIR |= 0x10;				// P5.4= output direction
	P5SEL |= 0x10;				// P5.4= MCLK option select

	P5DIR |= 0x20;				// P5.5= output direction
	P5SEL |= 0x20;				// P5.5= SMCLK option select

	P5DIR |= 0x40;				// P5.6= output direction
	P5SEL |= 0x40;				// P5.6= ACLK option select
#endif

#if defined(__C51__)
	init_mempool (&malloc_mempool, sizeof(malloc_mempool));
#endif // #if defined(__C51__)

	init_1ms_timer();

#ifdef CONSOLE
	memset(&UART_BUFF, 0, sizeof(UART_BUFF));
	InitUART();	// Uart Initial
#endif

	InitSPI();	//SPI Initial

	//Enable Interrupt for UBEC chip
	P1DIR_bit.P1DIR_0=0;
	P1IFG_bit.P1IFG_0=0;
	P1IES_bit.P1IES_0=1;
	P1IE_bit.P1IE_0=1;
}

#if 0
extern void _program_start(void);
void SystemReset(void)
{
	TRACE_puts("SystemReset");

	DisInt();
    	_program_start();
}
#endif
